﻿using Microsoft.Data.SqlClient;
using MyCommon.Helper;
using MyModels.Models;
using Newtonsoft.Json;
using SqlSugar;
using SqlSugar.Extensions;
using System.Reflection;
using System.Text;

namespace MyCommon.Seed
{
    public class DBSeed
    {
        // 需要初始化的数据存放位置
        private static string SeedDataFolder = "MyApi.Data.json/{0}.tsv";

        public static async Task SeedDataAsync(MyContext myContext, string webRoot)
        {
            try
            {
                if (string.IsNullOrEmpty(webRoot))
                {
                    throw new Exception("获取 wwwroot 路径时候异常了");
                }
                SeedDataFolder = Path.Combine(webRoot, SeedDataFolder);

                Console.WriteLine("********************* MyApi DataBase Set **********************");
                Console.WriteLine($"Master DB ConnectId:{myContext.Db.CurrentConnectionConfig.ConfigId}");
                Console.WriteLine($"Master DB Type:{myContext.Db.CurrentConnectionConfig.DbType}");
                Console.WriteLine($"Master DB ConnectionString:{myContext.Db.CurrentConnectionConfig.ConnectionString}");
                Console.WriteLine("********************* MyApi DataBase Set **********************");
                Console.WriteLine();

                // 创建数据库
                Console.WriteLine($"Create DataBase ...");

                if (myContext.Db.CurrentConnectionConfig.DbType == DbType.Oracle || myContext.Db.CurrentConnectionConfig.DbType == DbType.Dm)
                {
                    ConsoleHelper.WriteErrorLine("Oracle/DM 数据库不支持该操作，可以手动创建Oracle/DM数据库");
                }
                else
                {
                    // 创建数据库
                    myContext.Db.DbMaintenance.CreateDatabase();
                    SqlConnection.ClearAllPools();
                    ConsoleHelper.WriteSuccessLine("Database Created successfully!");
                }
                // 创建数据库表，遍历指定命名空间下的class
                Console.WriteLine("Create Tables ...");
                var path = AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory;
                var referencedAssemblies = Directory.GetFiles(path, "MyModels.dll").Select(Assembly.LoadFrom).ToArray();
                var modelTypes = referencedAssemblies.SelectMany(a => a.DefinedTypes)
                    .Select(t => t.AsType())
                    .Where(i => i.IsClass && i.Namespace is "MyModels.Models")
                    .ToArray();
                //modelTypes.ForEach(t =>
                //{
                //    if (!myContext.Db.DbMaintenance.IsAnyTable(t.Name))
                //    {
                //        Console.WriteLine($"表名称：{t.Name}");
                //        myContext.Db.CodeFirst.SetStringDefaultLength(50).SplitTables().InitTables(t);
                //    }
                //});

                myContext.Db.CodeFirst.SetStringDefaultLength(50).InitTables(modelTypes);
                ConsoleHelper.WriteSuccessLine("Tables created successfully!");
                Console.WriteLine();

                if(Appsettings.app("AppSettings", "SeedDBDataEnabled").ObjToBool())
                {
                    var settings = new JsonSerializerSettings();
                    JsonConvert.DefaultSettings = new Func<JsonSerializerSettings>(() =>
                    {
                        // 日期类默认格式化处理
                        settings.DateFormatHandling = DateFormatHandling.MicrosoftDateFormat;
                        settings.DateFormatString = "yyyy-MM-dd HH:mm:ss";

                        // 处理空值
                        settings.NullValueHandling = NullValueHandling.Ignore;
                        return settings;
                    });

                    Console.WriteLine("开始初始化数据");

                    #region 初始化数据库

                    await SeedTables<Modules>(myContext, settings,"Modules");

                    await SeedTables<Permission>(myContext, settings, "Permission");

                    await SeedTables<Role>(myContext, settings, "Role");

                    await SeedTables<RoleModulePermission>(myContext, settings, "RoleModulePermission");

                    await SeedTables<UserRole>(myContext, settings, "UserRole");

                    await SeedTables<SysUserInfo>(myContext, settings, "SysUserInfo");

                    await SeedTables<Department>(myContext, settings, "Department");

                    #endregion
                    ConsoleHelper.WriteSuccessLine("完成数据初始化工作");
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 泛型方法用于个表初始化数据
        /// </summary>
        /// <typeparam name="T">要初始化数据表 model类</typeparam>
        /// <param name="myContext">上下文</param>
        /// <param name="settings">反序列化设置</param>
        /// <param name="tableName">表名称</param>
        /// <returns></returns>
        private static async Task SeedTables<T>(MyContext myContext, JsonSerializerSettings settings,string tableName) where T : class,new()
        {
            if (!await myContext.Db.Queryable<T>().AnyAsync())
            {
                var data = JsonConvert.DeserializeObject<List<T>>(FileHelper.ReadFile(string.Format(SeedDataFolder, tableName), Encoding.UTF8), settings);
                myContext.GetEntityDB<T>().InsertRange(data);
                ConsoleHelper.WriteSuccessLine($"Table:{tableName} Seed Success");
            }
            else
            {
                ConsoleHelper.WriteWorningLine("Table:Modules already exists...");
            }
        }

    }
}
